package com.xy6.dpdemo.book.chapter19.composite;

import java.util.ArrayList;
import java.util.List;

import com.xy6.dpdemo.book.chapter19.composite.dept.finance.BranchFinanceService;
import com.xy6.dpdemo.book.chapter19.composite.dept.finance.BusinessFinanceService;
import com.xy6.dpdemo.book.chapter19.composite.dept.finance.FinanceDept;
import com.xy6.dpdemo.book.chapter19.composite.dept.finance.HeadFinanceService;
import com.xy6.dpdemo.book.chapter19.composite.dept.hr.BranchHrService;
import com.xy6.dpdemo.book.chapter19.composite.dept.hr.BusinessHrService;
import com.xy6.dpdemo.book.chapter19.composite.dept.hr.HeadHrService;
import com.xy6.dpdemo.book.chapter19.composite.dept.hr.HrDept;
import com.xy6.dpdemo.book.chapter19.composite.office.BranchOffice;
import com.xy6.dpdemo.book.chapter19.composite.office.BusinessOffice;
import com.xy6.dpdemo.book.chapter19.composite.office.HeadOffice;

/**
 * 设计一个简单OA系统，管理一个公司的组织结构
 * <p>总公司可以新增分公司、人力资源部、财务部，分公司可以新增办事处、人资部门、财务部门，
 * 办事处可以新增人资部门、财务部门
 * 
 * <pre>
 * 创建三个类，总公司、分公司、办事处，创建两个部门人资、财务，在各bean中添加属性，表示可以新增的对象。
 * 缺点：代码重复，总公司、分公司、办事处，除名称、下属机构不同外，其他属性及行为都相同。不灵活，如果组织变动，
 * 分公司不存在了，所有bean都要修改。
 * 改：将总公司、分公司、办事处共同的东西抽象为公司接口，接口中定义新增、删除公司、职责等方法，定义具体公司bean，
 * 实现公司接口，定义人资、财务bean，实现具体行为。
 * 组合模式。
 * 应用场景：需求是体现部分与整体层次的结构时，希望客户端忽略组合对象和单个对象的不同，统一使用组合结构中的所有对象。
 * 部分、整体场景，如树形菜单，文件、文件夹的管理。
 * 前端设计中的TreeView组件，C#中System.Web.UI.Control类。
 * 
 * 组合模式，将对象组合成树形结构，以表示“部分-整体”的层次结构。组合模式使得用户对单个对象和组合对象的使用具有一致性。
 * </pre>
 * 
 * @author zhang
 * @since 2017-06-27
 */
public class OAMain {

	public static void main(String[] args){
		test2();
	}
	
	@SuppressWarnings("unused")
	private static void test1(){
		// 初始化数据
		HeadOffice head = new HeadOffice();
		head.setName("总公司");
		head.setFinance(new FinanceDept("财务部", new HeadFinanceService(head)));
		head.setHr(new HrDept("人力资源部", new HeadHrService(head)));
		
		BranchOffice branch1 = new BranchOffice();
		branch1.setName("华南分公司");
		branch1.setFinance(new FinanceDept("财务部", new BranchFinanceService(branch1)));
		branch1.setHr(new HrDept("人力资源部", new BranchHrService(branch1)));
		
		BranchOffice branch2 = new BranchOffice();
		branch2.setName("华东分公司");
		branch2.setFinance(new FinanceDept("财务部", new BranchFinanceService(branch2)));
		branch2.setHr(new HrDept("人力资源部", new BranchHrService(branch2)));
		
		List<BranchOffice> listBranch = new ArrayList<>(2);
		listBranch.add(branch1);
		listBranch.add(branch2);
		head.setListBranch(listBranch);
		
		BusinessOffice biz1 = new BusinessOffice();
		biz1.setName("广州办事处");
		biz1.setFinance(new FinanceDept("财务部", new BusinessFinanceService(biz1)));
		biz1.setHr(new HrDept("人力资源部", new BusinessHrService(biz1)));
		
		List<BusinessOffice> listBiz1 = new ArrayList<>();
		listBiz1.add(biz1);
		branch1.setListBiz(listBiz1);
		
		BusinessOffice biz2 = new BusinessOffice();
		biz2.setName("广州办事处");
		biz2.setFinance(new FinanceDept("财务部", new BusinessFinanceService(biz2)));
		biz2.setHr(new HrDept("人力资源部", new BusinessHrService(biz2)));
		
		List<BusinessOffice> listBiz2 = new ArrayList<>();
		listBiz2.add(biz2);
		branch2.setListBiz(listBiz2);
		
		// 模拟工作流程
		head.getFinance().budget();
		head.getHr().recruit();
		
		branch1.getFinance().budget();
		branch1.getHr().recruit();
		
		biz1.getFinance().budget();
		biz1.getHr().recruit();
	}
	
	private static void test2(){
		ConcreteCompany root  = new ConcreteCompany("总公司");
		root.add(new HrDepartment("总公司人力资源部"));
		root.add(new FinanceDepartment("总公司财务部"));
		
		ConcreteCompany com1 = new ConcreteCompany("上海华东分公司");
		com1.add(new HrDepartment("上海华东分公司人力资源部"));
		com1.add(new FinanceDepartment("上海华东分公司财务部"));
		root.add(com1);
		
		ConcreteCompany com2 = new ConcreteCompany("南京办事处");
		com2.add(new HrDepartment("南京办事处人力资源部"));
		com2.add(new FinanceDepartment("南京办事处财务部"));
		com1.add(com2);
		
		ConcreteCompany com3 = new ConcreteCompany("杭州办事处");
		com3.add(new HrDepartment("杭州办事处人力资源部"));
		com3.add(new FinanceDepartment("杭州办事处财务部"));
		com1.add(com3);
		
		System.out.println("组织结构图：");
		root.display(1);
		
		System.out.println("职责：");
		root.duty();
	}
	
}
